package Assignment8;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        System.out.println("方案列表：");
        System.out.println("1. 用FileWriter直接写字符串或其对应的字节流；");
        System.out.println("2. 用DataOutputStream的writeUTF方法写入文件；");
        System.out.println("3. 实现Blob类（包含type、size和content等属性）并为其实现Serializable接口，使用该字符串实例化Blob对象，并用ObjectOutputStream将该对象序列化到文件中。");
        System.out.print("请输入您选择方案的号码：");
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        sc.close();
        String content = "你好，Java！";
        switch (num) { //idea推荐使用加强版的switch
            case 1 -> {
                Scheme1 scheme1 = new Scheme1(content);
                scheme1.writeTest1(content);
                scheme1.readTest1(scheme1.filename);
            }
            case 2 -> {
                Scheme2 scheme2 = new Scheme2(content);
                scheme2.writeTest2(content);
                scheme2.readTest2(scheme2.filename);
            }
            case 3 -> {
                Scheme3 scheme3 = new Scheme3(content);
                scheme3.writeTest3(content);
                scheme3.readTest3(scheme3.filename);
            }
            default -> System.out.println("请重启程序并输入正确的数字！");
        }
    }
}

/*****关于生成SHA1值方法的类*****/
class SHA1 {

    public static String str2SHA1(String str) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1"); //指明SHA-1
            md.update(str.getBytes(StandardCharsets.UTF_8)); //"utf-8"
            byte[] bytes = md.digest(); //得到字节数组
            return bytes2Hex(bytes); //返回字符串的SHA-1值
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    public static String bytes2Hex(byte[] bytes) {
        StringBuilder strb = new StringBuilder();
        for (byte aByte : bytes) {
            String hex = Integer.toHexString(aByte & 0xFF);
            if (hex.length() < 2) { //处理十六进制数只有1位的情况
                strb.append(0); //要补到2位
            }
            strb.append(hex);
        }
        return strb.toString();
    }
}

/*****方案1*****/
class Scheme1 {

    String filename;

    Scheme1(String content) {
        this.filename = SHA1.str2SHA1(content) + ".txt";
    }

    void writeTest1(String content) {
        File file = new File(filename);
        FileWriter fw = null;
        try {
            if (file.createNewFile()) {
                fw = new FileWriter(file);
                fw.write(content);
                fw.flush();
                fw.close();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    void readTest1(String filename) {
        FileReader fr = null;
        try {
            fr = new FileReader(filename);
            int k = 0;
            while (k != -1) {
                k = fr.read();
                System.out.print((char) k);
            }
            System.out.println();
            fr.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

}

/*****方案2*****/
class Scheme2 {

    String filename;

    Scheme2(String content) {
        this.filename = SHA1.str2SHA1(content) + ".txt";
    }

    void writeTest2(String content) {
        DataOutputStream dos = null;
        File file = new File(filename); // 文件名（相对路径）
        try {
            dos = new DataOutputStream(new FileOutputStream(file)); // 声明数据输出流对象，实例化数据输出流对象
            dos.writeUTF(content);
            dos.close();    // 关闭输出流
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    void readTest2(String filename) {
        DataInputStream dis = null; // 声明数据输入流对象
        File file = new File(filename); // 文件名（相对路径）
        try {
            dis = new DataInputStream(new FileInputStream(file)); // 实例化数据输入流对象
            System.out.println(dis.readUTF());
            dis.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

}

/*****方案3*****/
class Scheme3 {

    String filename;

    Scheme3(String content) {
        this.filename = SHA1.str2SHA1(content);
    }

    void writeTest3(String content) {
        Blob blob = new Blob(content);
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream(filename));
            oos.writeObject(blob); // 把对象写进文件中
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (oos != null)
                    oos.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    void readTest3(String filename) {
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream(filename));
            Blob blob = (Blob) ois.readObject();
            System.out.println("blob " + blob.size + "\0" + blob.content);
        } catch (ClassNotFoundException | IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (ois != null)
                    ois.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

}

class Blob implements Serializable {

    String type;
    int size;
    String content;

    Blob(String content) {
        this.type = "String";
        this.size = content.getBytes(StandardCharsets.UTF_8).length;
        this.content = content;
    }

}